package tool

import (
	"net/http"
	"strings"
	"io/ioutil"
	"adai.design/homeserver/devices"
	"encoding/json"
	"sync"
	"time"
)

type Message struct {
	Path 	string		`json:"path"`
	Method  string		`json:"method"`
	State 	string		`json:"state,omitempty"`
	Data 	json.RawMessage		`json:"data,omitempty"`
}

type Characteristic struct {
	AccessoryID 	string		`json:"aid"`
	ServiceId 		int			`json:"sid"`
	CharacteristicId  int 		`json:"cid"`
	Value 	 	interface{}		`json:"value"`
}


const (
	MsgPathAccessories = "accessories"
	MsgPathCharacteristics = "characteristic"
	MsgPathContainer = "container"

	MsgMethodPost = "post"
	MsgMethodGet = "get"
	MsgMethodPut = "put"
)


type workers struct {
	sync.Mutex
	pkg 	chan *devices.MessagePkg
}

func (w *workers) Handle(pkg *devices.MessagePkg) {
	if w.pkg != nil {
		w.pkg <- pkg
	}
}

func (w *workers) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	path := strings.Split(request.URL.Path, "/")
	if len(path) <= 2 {
		response.Write([]byte("invalid url"))
		return
	}

	dev := path[2]
	body, err := ioutil.ReadAll(request.Body)
	if err != nil {
		response.Write([]byte("invalid data format"))
		return
	}

	var message devices.Message
	err = json.Unmarshal(body, &message)
	if err != nil {
		response.Write([]byte("json format err"))
		return
	}

	w.Lock()
	devices.AddObserver(w)
	w.pkg = make(chan *devices.MessagePkg, 4)
	defer func() {
		devices.RemoveObserver(w)
		close(w.pkg)
		w.pkg = nil
		w.Unlock()
	}()

	pkg := &devices.MessagePkg{
		DevId: dev,
		Msg: &message,
	}
	err = devices.SendPackage(pkg)

	select {
	case pkg, ok := <- w.pkg:
		if ok {
			buf, _ := json.Marshal(pkg.Msg)
			response.Write(buf)
			return
		}

	case <-time.After(time.Second * 5):
		response.Write([]byte("timeout"))
		return
	}

	response.Write([]byte("error"))
}

func init() {
	router["workers"] = &workers{}
}